<?php

use think\Request;
use think\Validate;
use think\Db;
use think\Loader;
use delayQueue\DelayQueue;

/**
 * 检查表单令牌
 * @param string $token 表单令牌
 * @return      bool
 * */
function checkToken($token)
{
    $data = ['__token__' => $token];
    $rule = ['__token__' => 'token'];
    $msg = ['__token__' => '请不要刷新该页面！'];
    //引入验证类
    $validate = Validate::make($rule, $msg);
    if ($validate->check($data)) {
        return true;
    } else {
        return false;
    }
}

/**
 * 按综合方式输出通信数据（后台异步返回信息专用）
 * @param integer $result 状态码
 * @param string  $msg    提示信息
 * @param array   $url    参考 url() 方法；链接：https://www.kancloud.cn/manual/thinkphp5/118041
 * @param int     $timer  跳转时间
 * @return      string
 */
function adminReturn($result, $msg = '', $url = '', $extra = [], $timer = 1000)
{
    if ($result == 1) {
        $message = [
            'result' => $result,
            'msg' => $msg,
            'url' => $url,
            'timer' => intval($timer),
            'extra' => $extra
        ];
    } else {
        $request = Request::instance();
        $token = $request->token();

        $message = [
            'result' => $result,
            'msg' => $msg,
            'url' => $url,
            'token' => $token,
            'timer' => intval($timer)
        ];
    }

    echo json_encode($message, JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * 获取顶级菜单ID
 * @param int $id 子菜单id
 * */
function getTopId($id)
{
    $info = Db::name('menu')->field('id,pid,level')->where(['id' => $id])->find();
    if ($info['level'] > 1) {
        return getTopId($info['pid']);
    } else {
        return $info['id'];
    }
}

/**
 * 获取request_uri（去除参数）
 * */
function getRequestUri()
{
    $request_uri = $_SERVER['PATH_INFO'];
    $request_uri_arr = explode('/', $request_uri);
    return '/' . $request_uri_arr[1] . '/' . $request_uri_arr[2] . '/' . $request_uri_arr[3];
}

/**
 * 点击顶部菜单获取匹配的左侧菜单
 * @param string $id 顶部菜单id
 * @return      bool
 * */
function showLeftMenu($id)
{
    $request_uri = getRequestUri();

    $info = Db::name('menu')->field('id,pid')->where(['url' => str_replace('.html', '', $request_uri)])->find();
    $top_id = getTopId($info['id']);

    if ($top_id == $id) {
        return true;
    }

    return false;
}

/**
 * 顶部菜单高亮
 * */
function topMenuActive($id = 0)
{
    if ($id == 0) {
        $request_uri = getRequestUri();
        $self_id = Db::name('menu')->where(['url' => str_replace('.html', '', $request_uri)])->value('id');

        return $self_id ? topMenuActive($self_id) : $id;
    } else {
        $pid = Db::name('menu')->where(['id' => $id])->value('pid');

        return $pid ? topMenuActive($pid) : $id;
    }
}

/**
 * 左侧菜单高亮
 * @param int $id    id
 * @param int $level 2：左侧分组菜单，3：左侧分组子菜单
 * @return      bool
 * */
function leftMenuActive($id, $level)
{
    $request_uri = getRequestUri();

    if ($level == 2) {
        $count = Db::name('menu')->where(['pid' => $id, 'is_show' => 1, 'level' => $level])->count();
        if ($count > 0) {
            //有显示的子菜单
            $info = Db::name('menu')->field('pid')->where(['url' => str_replace('.html', '', $request_uri), 'pid' => ['gt', 0]])->find();
            if ($info['pid'] == $id) {
                return true;
            } else {
                $group_info = Db::name('menu')->field('pid')->where(['id' => $info['pid']])->find();
                if ($group_info['pid'] == $id) {
                    return true;
                }
            }
        } else {
            //无显示的子菜单
            $info = Db::name('menu')->field('id,pid')->where(['url' => str_replace('.html', '', $request_uri), 'pid' => ['gt', 0]])->find();
            if ($info['id'] == $id) {
                return true;
            } else {
                if ($info['pid'] == $id) {
                    return true;
                } else {
                    $group_info = Db::name('menu')->field('pid')->where(['id' => $info['pid']])->find();
                    if ($group_info['pid'] == $id) {
                        return true;
                    }
                }
            }
        }
    } else if ($level == 3) {
        $info = Db::name('menu')->field('id')->where(['url' => str_replace('.html', '', $request_uri), 'pid' => ['gt', 0], 'level' => $level])->find();
        if ($info['id'] == $id) {
            return true;
        } else {
            $parent_info = Db::name('menu')->field('pid')->where(['url' => str_replace('.html', '', $request_uri), 'pid' => ['gt', 0], 'level' => 4])->find();
            if ($parent_info['pid'] == $id) {
                return true;
            }
        }
    }
}

/**
 * 更新URL（顶部菜单，分组菜单）
 * 调用时机：当对level=3的菜单操作完成后，执行该方法
 * */
function renewTopAndGroupUrl()
{
    //顶部菜单
    $top_list = Db::name('menu')->field('id,url')->where(['pid' => 0, 'level' => 1, 'status' => 1, 'is_show' => 1])->order('sort asc')->select();
    if ($top_list) {
        foreach ($top_list as &$v) {
            //分组菜单
            $group_list = Db::name('menu')->field('id,pid,url')->where(['pid' => $v['id'], 'level' => 2, 'status' => 1, 'is_show' => 1])->order('sort asc')->select();
            if ($group_list) {
                foreach ($group_list as $key => &$val) {
                    //第一个子菜单
                    $son_first_info = Db::name('menu')->field('id,pid,url')->where(['pid' => $val['id'], 'level' => 3, 'status' => 1, 'is_show' => 1])->order('sort asc')->find();

                    if ($son_first_info) {
                        //更新分组菜单URL
                        Db::name('menu')->where(['id' => $val['id']])->update(['url' => $son_first_info['url'], 'update_time' => time()]);
                        //更新顶部菜单URL
                        if ($key == 0) Db::name('menu')->where(['id' => $v['id']])->update(['url' => $son_first_info['url'], 'update_time' => time()]);
                    } else {
                        //更新顶部菜单URL
                        if ($key == 0) Db::name('menu')->where(['id' => $v['id']])->update(['url' => $val['url'], 'update_time' => time()]);
                    }
                }
            }
        }
    }
}

/**
 * 获取上级菜单名称
 * @param int $pid 上级菜单id
 * @return      string
 **/
function getParentMenuName($pid)
{
    if ($pid > 0) {
        $info = model('menu')->get($pid);

        return $info ? $info->name : '无';
    } else {
        return '无';
    }
}

/**
 * 获取下级菜单id
 * */
function getSonMenuId($id, &$son_ids = [])
{
    if ($id) {
        $son_list = Db::name('menu')->field('id')->where(['pid' => ['IN', $id]])->select();
        if ($son_list) {
            foreach ($son_list as &$v) {
                $son_ids[] = $v['id'];
            }
            getSonMenuId(array_column($son_list, 'id'), $son_ids);
        } else {
            return $son_ids;
        }
    }
}

/**
 * 获取上级菜单ID
 * @param int $pid 上级菜单id
 * @return      int
 **/
function getParentMenuId($pid)
{
    if ($pid > 0) {
        $info = model('menu')->get($pid);

        return $info ? $info->id : 0;
    } else {
        return 0;
    }
}

/**
 * 获取访问授权未选中的父级菜单ID
 * @param int   $id    菜单id
 * @param array $rules 待加入未选中父级菜单ID数组
 * */
function getNoCheckParentId($id, &$rules)
{
    $pid = Db::name('menu')->where(['id' => $id])->column('pid');
    if ($pid[0] > 0) {
        $parent_id = getParentMenuId($pid[0]);
        if ($parent_id > 0 && !in_array($parent_id, $rules)) {
            $rules[] = $parent_id;
            return getNoCheckParentId($parent_id, $rules);
        } else {
            return $rules;
        }
    }
}

/**
 * 判断访问授权复选框是否选中
 * @param int $group_id 全选分组id
 * @param int $menu_id  菜单ID
 * */
function authChecked($group_id, $menu_id)
{
    $rules = Db::name('auth_group')->where(['id' => $group_id])->column('show_rules');
    $rules = $rules[0];

    if (in_array($menu_id, explode(',', $rules))) {
        return 'checked';
    } else {
        return '';
    }
}

/**
 * 后台接收checkbox选中的值
 * @param string $arr 复选框接收数据
 * @return string
 * */
function getCheckBox($arr)
{
    $ids = implode(',', array_keys($arr));
    return $ids;
}


/**
 * 获取列标
 * @param int $length 列标长度
 * @return array
 * */
function getLetterList($length)
{
    $arr = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'];
    return array_slice($arr, 0, $length);
}

/**
 * 导出excel
 * @param string $title 文件名
 * @param array  $th    表头；例 ==> ['时间', '销售总额', '应发收益统计', '冻结收益总额', '充值总金额', '可用收益支付总额']
 * @param array  $td    数据下标；例 ==> ['date', 'all_order_price', 'all_get_profit', 'all_frozen_profit', 'all_recharge_profit', 'all_pay_profit']
 * @param array  $data  数据
 * */
function exportExcel($title, $th, $td, $data)
{
    // 文件名和文件类型
    $fileName = $title;
    $fileType = "xls";

    $obj = new PHPExcel();

    // 设置当前sheet
    $obj->setActiveSheetIndex(0);

    // 设置当前sheet的名称
    $obj->getActiveSheet()->setTitle($title);

    $list = getLetterList(count($th));

    // 填充第一行数据
    $activeSheet = $obj->getActiveSheet();
    for ($i = 0; $i < count($list); $i++) {
        $activeSheet->setCellValue($list[$i] . '1', $th[$i]);
    }
    // 填充第n(n>=2, n∈N*)行数据
    $data_length = count($data);
    for ($i = 0; $i < $data_length; $i++) {
        for ($j = 0; $j < count($td); $j++) {
            $activeSheet->setCellValue($list[$j] . ($i + 2), $data[$i][$td[$j]]);
        }
    }

    // 设置加粗和左对齐
    foreach ($list as $col) {
        // 设置第一行加粗
        $activeSheet->getStyle($col . '1')->getFont()->setBold(true);
        // 设置第1-n行，居中对齐
        for ($i = 1; $i <= $data_length + 1; $i++) {
            $activeSheet->getStyle($col . $i)->getAlignment()->setHorizontal(\PHPExcel_Style_Alignment::HORIZONTAL_CENTER);
        }
    }

    // 设置列宽
    for ($i = 0; $i < count($list); $i++) {
        $activeSheet->getColumnDimension($list[$i])->setWidth(25);
    }

    $fileName = urlencode($fileName);

    // 导出
    ob_clean();
    if ($fileType == 'xls') {
        header('Content-Type: application/vnd.ms-excel');
        header('Content-Disposition: attachment;filename="' . $fileName . '.xls');
        header('Cache-Control: max-age=1');
        $objWriter = new \PHPExcel_Writer_Excel5($obj);
        $objWriter->save('php://output');
        exit;
    } elseif ($fileType == 'xlsx') {
        header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
        header('Content-Disposition: attachment;filename="' . $fileName . '.xlsx');
        header('Cache-Control: max-age=1');
        $objWriter = \PHPExcel_IOFactory::createWriter($obj, 'Excel2007');
        $objWriter->save('php://output');
        exit;
    }
}

/**
 * 生成签名
 * */
function generateSign($params, $secretKey) {
    // 先排参（字典序）
    ksort($params);
    // 拼接字符串，例如 key1=value1&key2=value2...
    $str = http_build_query($params);
    // 用密钥和字符串做 HMAC-SHA256
    return hash_hmac('sha256', $str, $secretKey);
}

/**
 * 校验签名
 * */
function verifySign($params, $secretKey) {
    if (!isset($params['sign'])) return false;
    $sign = $params['sign'];
    unset($params['sign']);

    // 校验时间戳，避免重放攻击
    if (abs(time() - $params['timestamp']) > 300) {  // 5分钟有效期
        return false;
    }

    return $sign === generateSign($params, $secretKey);
}